package fina2.dcs.mail.owa;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TimeZone;

import javax.mail.Authenticator;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;

import org.apache.log4j.Logger;

import fina2.dcs.mail.MailReaderBase;
import fina2.dcs.mail.MailReaderPOP3;
import fina2.dcs.mail.manager.AttachInfo;
import fina2.dcs.mail.manager.MailPropsKey;
import fina2.dcs.mail.manager.MailUser;
import fina2.dcs.mail.util.MailUtil;

@SuppressWarnings("serial")
public class MailReaderImplOWA implements MailReaderBase {
	private Logger log = Logger.getLogger(getClass());
	private static String folderName = "INBOX";

	private String host;
	private int port;

	private Session session = null;
	private Store store = null;

	private DateFormat df = null;

	private MailUser mailUser;

	public MailReaderImplOWA(MailUser mailUser) {
		this.mailUser = mailUser;
		initArgs();

	}

	@Override
	public List<AttachInfo> getNewAttahcments(Date date) throws MessagingException {
		List<AttachInfo> mails = new ArrayList<AttachInfo>();

		Properties prop = createExchangeMailProperties(date);
		Authenticator auth = new MailUtil.MyAuthenticator(mailUser.getUser(), mailUser.getPassword());
		session = Session.getInstance(prop, auth);
		try {
			store = session.getStore("pop3");
		} catch (NoSuchProviderException e) {
			log.error(e.getMessage(), e);
		}

		log.info("Start Connection!");
		// System.out.println(mailUser);
		store.connect(host, port, mailUser.getUser(), mailUser.getPassword());

		log.info("Store Connect.");

		String storeClass = store.getClass().getName();
		if (!"org.exjello.mail.ExchangeStore".equals(storeClass)) {
			throw new MessagingException("Provider('Exjello') Not Found!");
		}
		Folder folder = openFolder(folderName);

		log.info("Open \"Inbox\" Folder.");

		if (folder != null) {
			if (date == null) {
				date = new Date();
			}

			log.info("Search Mails...");

			Message[] messages = folder.getMessages();

			log.info("End Search.");

			for (Message m : messages) {
				DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
				df.setTimeZone(TimeZone.getTimeZone("Zulu"));
				String parseDate = df.format(m.getSentDate());
				String dateString = df.format(date);
				try {
					if (df.parse(parseDate).compareTo(df.parse(dateString)) > 0) {
						log.info("New Message. Message From:" + Arrays.toString(m.getFrom()));

						AttachInfo info = new AttachInfo();
						info.setReceivedDate(m.getReceivedDate());
						info.setAddress(m.getFrom());
						try {
							Map<String, byte[]> map = MailUtil.getAttachments(m, mailUser);
							info.setAttachFiles(map);
							log.info(info);
							mails.add(info);
						} catch (Exception ex) {
							log.info("Ignore Message From : " + Arrays.toString(m.getFrom()) + " | Subject : " + m.getSubject() + " | Message(toString) : " + m.toString() + " | Send Date : " + m.getSentDate());
							log.error(ex.getMessage(), ex);
						}
					}
				} catch (Exception e) {
					log.error(e.getMessage(), e);
				}
			}
			folder.close(true);
		} else {
			throw new MessagingException("Invalid folder");
		}
		store.close();
		return mails;
	}

	@Override
	public MailUser getMailUser() {
		return this.mailUser;
	}

	private void initArgs() {
		host = MailUtil.getProperty(MailPropsKey.MAIL_POP3_HOST, mailUser.getProperties());
		port = Integer.parseInt(MailUtil.getProperty(MailPropsKey.MAIL_POP3_PORT, mailUser.getProperties()));
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof MailReaderPOP3) {
			MailReaderImplOWA m = (MailReaderImplOWA) obj;
			return this.mailUser.equals(m.mailUser);
		}
		return false;
	}

	private Folder openFolder(String fName) throws MessagingException {
		Folder folder = store.getFolder(fName);
		if (folder == null) {
			throw new MessagingException("Invalid folder");
		}
		folder.open(Folder.READ_ONLY);
		return folder;
	}

	private Properties createExchangeMailProperties(Date mailLastReadDate) {
		Map<String, String> sysProps = mailUser.getProperties();
		Properties props = new Properties();

		if (df == null)
			df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
		df.setTimeZone(TimeZone.getTimeZone("Zulu"));
		String parseDate = df.format(mailLastReadDate);
		StringBuilder sb = new StringBuilder(parseDate);
		sb.replace(sb.indexOf("+"), parseDate.length(), "Z");
		parseDate = sb.toString();
		props.setProperty("org.exjello.mail.filterlastcheck", parseDate);
		props.setProperty(MailPropsKey.EXJELLO_MAIL_UNFILTERED, sysProps.get(MailPropsKey.EXJELLO_MAIL_UNFILTERED));
		props.setProperty(MailPropsKey.EXJELLO_MAIL_LIMIT, sysProps.get(MailPropsKey.EXJELLO_MAIL_LIMIT));
		props.setProperty(MailPropsKey.EXJELLO_MAIL_DELETE, sysProps.get(MailPropsKey.EXJELLO_MAIL_DELETE));
		props.setProperty(MailPropsKey.MAIL_POP3_PORT, sysProps.get(MailPropsKey.MAIL_POP3_PORT));
		props.setProperty(MailPropsKey.MAIL_POP3_SSL_ENABLE, sysProps.get(MailPropsKey.MAIL_POP3_SSL_ENABLE));
		props.setProperty(MailPropsKey.MAIL_POP3_CONNECTION_TIMEUT, sysProps.get(MailPropsKey.MAIL_POP3_CONNECTION_TIMEUT));
		props.setProperty(MailPropsKey.MAIL_SMTP_CONNECTION_TIMEUT, sysProps.get(MailPropsKey.MAIL_SMTP_CONNECTION_TIMEUT));
		props.setProperty(MailPropsKey.MAIL_SMTP_SSL_ENABLE, sysProps.get(MailPropsKey.MAIL_SMTP_SSL_ENABLE));
		props.setProperty(MailPropsKey.MAIL_SMTP_PORT, sysProps.get(MailPropsKey.MAIL_SMTP_PORT));

		String mailBoox = sysProps.get(MailPropsKey.EXCHANGE_MAILBOX);

		props.put(MailPropsKey.EXCHANGE_MAILBOX, mailBoox);
		props.put("mail.pop3.from", mailBoox);
		props.put("mail.pop3.user", mailUser.getUser());
		props.put("mail.pop3.host", host);
		props.put("mail.smtp.from", mailBoox);
		props.put("mail.smtp.user", mailUser.getUser());

		return props;
	}

}
